﻿using System;
using System.Collections.Generic;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Mechanical;
using YArchitech.Revit;

namespace YArchitech.Temp
{
	internal static class RevitDataExchange
	{
		public static HYShapeProfile ToShape(ConnectorProfileType cpt)
		{
            return (HYShapeProfile)cpt;
		}

		public static ConnectorProfileType ToShape(HYShapeProfile dsp)
		{
            return (ConnectorProfileType)dsp;
		}

		public static void ToDuctSpecification(Connector conn, ref HYDuctSpecification ds)
		{
			ds.Shape = RevitDataExchange.ToShape(conn.Shape);
			ds.Tag = conn;
			if (ds.Shape == HYShapeProfile.Round)
			{
				ds.Diameter = (int)RevitUtils.Fix(RevitUtils.DistanceToInternal(2.0 * conn.Radius) * 1000.0, 3);
				return;
			}
			ds.Width = (int)RevitUtils.Fix(RevitUtils.DistanceToInternal(conn.Width) * 1000.0, 3);
			ds.Height = (int)RevitUtils.Fix(RevitUtils.DistanceToInternal(conn.Height) * 1000.0, 3);
		}

		public static HYMEPObject CreateMEPObject(Element element)
		{
			HYMEPObject result;
			if (DbUtils.IsDuct(element))
			{
				result = RevitDataExchange.CreateStraight(element as Duct);
			}
			else if (DbUtils.IsMechanicalEquipment(element))
			{
				result = RevitDataExchange.CreatEquipment(element as FamilyInstance);
			}
			else if (DbUtils.IsDuctTerminal(element))
			{
				result = RevitDataExchange.CreateTerminal(element as FamilyInstance);
			}
			else if (DbUtils.IsDuctFitting(element))
			{
				result = RevitDataExchange.CreateFitting(element as FamilyInstance);
			}
			else if (DbUtils.IsDuctAccessory(element))
			{
				result = RevitDataExchange.CreateAccessory(element as FamilyInstance);
			}
			else
			{
				if (!DbUtils.IsFlexDuct(element))
				{
					return null;
				}
				result = RevitDataExchange.CreateStraight(element as FlexDuct);
			}
			return result;
		}

		public static HYDuctFitting CreateFitting(FamilyInstance fi)
		{
			MechanicalFitting mechanicalFitting = fi.MEPModel as MechanicalFitting;
			if (mechanicalFitting == null)
			{
				return null;
			}
			double num = RevitUtils.GetValue(fi, BuiltInParameter.RBS_LOSS_COEFFICIENT);
			if (num == 0.0)
			{
				num = RevitUtils.GetCoefiection(fi, "局阻系数");
			}
			string familyInstanceName = RevitUtils.GetFamilyInstanceName(fi);
			HYDuctFitting hyductFitting;
            switch ((int)mechanicalFitting.PartType)
			{
			case 5:
				hyductFitting = RevitDataExchange.CreateElbow(fi);
				goto IL_C1;
			case 6:
				hyductFitting = new HYDuctTee();
				goto IL_C1;
			case 7:
				hyductFitting = new HYDuctTransition
				{
					Id = fi.Id.IntegerValue,
					Name = RevitUtils.GetFamilyInstanceName(fi)
				};
				goto IL_C1;
			case 8:
				hyductFitting = new HYDuctCross();
				goto IL_C1;
			case 10:
				hyductFitting = new HYDuctTaper();
				goto IL_C1;
			case 11:
				hyductFitting = new HYDuctTaper();
				goto IL_C1;
			}
			hyductFitting = new HYDuctFitting();
			IL_C1:
			if (hyductFitting != null)
			{
				hyductFitting.Id = fi.Id.IntegerValue;
				hyductFitting.Coefficient = num;
				hyductFitting.Name = familyInstanceName;
			}
			return hyductFitting;
		}

		public static HYDuctAccessory CreateAccessory(FamilyInstance fi)
		{
			HYDuctAccessory hyductAccessory = new HYDuctAccessory();
			hyductAccessory.Id = fi.Id.IntegerValue;
			hyductAccessory.Coefficient = RevitUtils.GetValue(fi, BuiltInParameter.RBS_LOSS_COEFFICIENT);
			hyductAccessory.ShockResistance = 0.0;
			hyductAccessory.Name = RevitUtils.GetFamilyInstanceName(fi);
			HYDuctSpecification inPort = new HYDuctSpecification(HYShapeProfile.Rectangular, 800, 320);
			List<Connector> elementConnectors = RevitUtils.GetElementConnectors(fi);
			List<Connector> list = new List<Connector>();
			if (elementConnectors.Count > 0)
			{
				foreach (Connector connector in elementConnectors)
				{
					if (connector.Domain == (Autodesk.Revit.DB.Domain)1)
					{
						list.Add(connector);
					}
				}
				if (list.Count > 0)
				{
					Connector connector2 = list[0];
					RevitDataExchange.ToDuctSpecification(connector2, ref inPort);
					hyductAccessory.InPort = inPort;
					hyductAccessory.ShockResistance = RevitUtils.PressureToInternal(connector2.PressureDrop);
				}
			}
			if (hyductAccessory.ShockResistance == 0.0)
			{
				hyductAccessory.ShockResistance = RevitUtils.GetValue(fi, "局部阻力");
			}
			return hyductAccessory;
		}

		public static HYDuctAccessory CreatEquipment(FamilyInstance fi)
		{
			HYDuctAccessory hyductAccessory = new HYDuctAccessory();
			hyductAccessory.Id = fi.Id.IntegerValue;
			hyductAccessory.Coefficient = 0.0;
			hyductAccessory.ShockResistance = 0.0;
			hyductAccessory.Name = RevitUtils.GetFamilyInstanceName(fi);
			HYDuctSpecification inPort = new HYDuctSpecification(HYShapeProfile.Rectangular, 800, 320);
			List<Connector> elementConnectors = RevitUtils.GetElementConnectors(fi);
			List<Connector> list = new List<Connector>();
			if (elementConnectors.Count > 0)
			{
				foreach (Connector connector in elementConnectors)
				{
					if (connector.Domain == (Autodesk.Revit.DB.Domain)1)
					{
						list.Add(connector);
					}
				}
				if (list.Count > 0)
				{
					RevitDataExchange.ToDuctSpecification(list[0], ref inPort);
					hyductAccessory.InPort = inPort;
				}
			}
			return hyductAccessory;
		}

		public static HYDuctStraight CreateStraight(Duct revitDuct)
		{
			HYDuctStraight hyductStraight = new HYDuctStraight();
			hyductStraight.IsRiserDuct = RevitUtils.IsRiserDuct(revitDuct);
			hyductStraight.Id = revitDuct.Id.IntegerValue;
			HYDuctSpecification section = new HYDuctSpecification(HYShapeProfile.Rectangular, 800, 320);
			RevitDataExchange.ToDuctSpecification(RevitUtils.GetMEPObjectConnector(revitDuct), ref section);
			hyductStraight.Section = section;
			hyductStraight.Number = "RS_" + RevitUtils.GetRevitNumber(revitDuct);
			hyductStraight.Length = RevitUtils.GetCurveLength(revitDuct, BuiltInParameter.CURVE_ELEM_LENGTH);
			hyductStraight.Velocity = RevitUtils.GetVelocity(revitDuct, BuiltInParameter.RBS_VELOCITY);
			hyductStraight.AddFlow = RevitUtils.GetAdditionFlow(revitDuct, BuiltInParameter.RBS_ADDITIONAL_FLOW);
			RevitUtils.GetPressure(revitDuct, BuiltInParameter.RBS_VELOCITY_PRESSURE);
			RevitUtils.GetValue(revitDuct, BuiltInParameter.RBS_LOSS_COEFFICIENT);
            double rm = UnitConvert.CovertFromAPI((DisplayUnitType)38, RevitUtils.GetValue(revitDuct, BuiltInParameter.RBS_FRICTION));
			hyductStraight.Rm = rm;
			hyductStraight.FrictionalResistance = RevitUtils.GetPressure(revitDuct, BuiltInParameter.RBS_PRESSURE_DROP);
			hyductStraight.Resistance = hyductStraight.ShockResistance + hyductStraight.FrictionalResistance;
			hyductStraight.Re = RevitUtils.GetValue(revitDuct, BuiltInParameter.RBS_REYNOLDSNUMBER_PARAM);
			return hyductStraight;
		}

		public static HYDuctStraight CreateStraight(FlexDuct revitDuct)
		{
			HYDuctStraight hyductStraight = new HYDuctStraight();
			hyductStraight.Id = revitDuct.Id.IntegerValue;
			HYDuctSpecification section = new HYDuctSpecification(HYShapeProfile.Rectangular, 800, 320);
			RevitDataExchange.ToDuctSpecification(RevitUtils.GetMEPObjectConnector(revitDuct), ref section);
			hyductStraight.Section = section;
			hyductStraight.Number = "RF_" + RevitUtils.GetRevitNumber(revitDuct);
			hyductStraight.Length = RevitUtils.GetCurveLength(revitDuct, BuiltInParameter.CURVE_ELEM_LENGTH);
			hyductStraight.Velocity = RevitUtils.GetVelocity(revitDuct, BuiltInParameter.RBS_VELOCITY);
			hyductStraight.AddFlow = RevitUtils.GetAdditionFlow(revitDuct, BuiltInParameter.RBS_ADDITIONAL_FLOW);
			RevitUtils.GetPressure(revitDuct, BuiltInParameter.RBS_VELOCITY_PRESSURE);
			RevitUtils.GetValue(revitDuct, BuiltInParameter.RBS_LOSS_COEFFICIENT);
            double rm = UnitConvert.CovertFromAPI((DisplayUnitType)38, RevitUtils.GetValue(revitDuct, BuiltInParameter.RBS_FRICTION));
			hyductStraight.Rm = rm;
			hyductStraight.FrictionalResistance = RevitUtils.GetPressure(revitDuct, BuiltInParameter.RBS_PRESSURE_DROP);
			hyductStraight.Resistance = hyductStraight.ShockResistance + hyductStraight.FrictionalResistance;
			hyductStraight.Re = RevitUtils.GetValue(revitDuct, BuiltInParameter.RBS_REYNOLDSNUMBER_PARAM);
			return hyductStraight;
		}

		public static HYDuctElbow CreateElbow(FamilyInstance fi)
		{
			HYDuctElbow hyductElbow = new HYDuctElbow();
			hyductElbow.Id = fi.Id.IntegerValue;
			hyductElbow.Coefficient = RevitUtils.GetValue(fi, BuiltInParameter.RBS_LOSS_COEFFICIENT);
			hyductElbow.Name = RevitUtils.GetFamilyInstanceName(fi);
			HYDuctSpecification hyductSpecification = new HYDuctSpecification(HYShapeProfile.Rectangular, 800, 320);
			List<Connector> elementConnectors = RevitUtils.GetElementConnectors(fi);
			if (elementConnectors.Count > 1)
			{
				Connector connector = elementConnectors[0];
				Connector connector2 = elementConnectors[1];
				XYZ basisZ = connector.CoordinateSystem.BasisZ;
				XYZ basisZ2 = connector2.CoordinateSystem.BasisZ;
				XYZ vec = basisZ.CrossProduct(basisZ2);
				hyductElbow.IsHorizontal = GeUtils.IsParallel(vec, XYZ.BasisZ);
				hyductElbow.Angle = RevitUtils.GetConnectorAngle(connector, connector2);
				RevitDataExchange.ToDuctSpecification(connector, ref hyductSpecification);
			}
			hyductElbow.InPort = hyductSpecification;
			hyductElbow.OutPort = hyductSpecification;
			return hyductElbow;
		}

		public static void GetTeeLinkInfo(HYDuctTee tee, Connector teeIn, Connector teeOut, Connector side, Connector crossSide)
		{
			HYDuctSpecification inPort = new HYDuctSpecification(HYShapeProfile.Rectangular, 800, 320);
			RevitDataExchange.ToDuctSpecification(teeIn, ref inPort);
			HYDuctSpecification outPort = new HYDuctSpecification(HYShapeProfile.Rectangular, 800, 320);
			RevitDataExchange.ToDuctSpecification(teeOut, ref outPort);
			HYDuctSpecification sidePort = new HYDuctSpecification(HYShapeProfile.Rectangular, 800, 320);
			RevitDataExchange.ToDuctSpecification(side, ref sidePort);
			tee.InPort = inPort;
			tee.OutPort = outPort;
			tee.SidePort = sidePort;
			tee.Angle = Math.PI - RevitUtils.GetConnectorAngle(teeIn, teeOut);
			tee.SideAngle = RevitUtils.GetConnectorAngle(teeOut, side);
			if (tee is HYDuctCross)
			{
				HYDuctSpecification side2Port = new HYDuctSpecification(HYShapeProfile.Rectangular, 800, 320);
				RevitDataExchange.ToDuctSpecification(crossSide, ref side2Port);
				HYDuctCross hyductCross = tee as HYDuctCross;
				hyductCross.Side2Port = side2Port;
				hyductCross.Side2Angle = RevitUtils.GetConnectorAngle(teeOut, crossSide);
			}
		}

		public static HYDuctTerminal CreateTerminal(FamilyInstance fi)
		{
			if (fi == null)
			{
				return null;
			}
			HYDuctTerminal hyductTerminal = new HYDuctTerminal();
			hyductTerminal.Id = fi.Id.IntegerValue;
			hyductTerminal.Name = RevitUtils.GetFamilyInstanceName(fi);
			HYDuctSpecification port = new HYDuctSpecification(HYShapeProfile.Rectangular, 800, 320);
			Connector mepobjectConnector = RevitUtils.GetMEPObjectConnector(fi.MEPModel);
			RevitDataExchange.ToDuctSpecification(mepobjectConnector, ref port);
			hyductTerminal.Port = port;
			hyductTerminal.Flow = RevitUtils.FlowToInternal(mepobjectConnector.Flow);
			hyductTerminal.PressureDrop = RevitUtils.PressureToInternal(mepobjectConnector.PressureDrop);
			hyductTerminal.Resistance = 0.0;
			hyductTerminal.DynamicPressure = RevitUtils.PressureToInternal(mepobjectConnector.VelocityPressure);
			Parameter parameter = fi.GetParameter("阻力损失");
			if (parameter == null)
			{
				parameter = fi.GetParameter("水头损失");
			}
			if (parameter != null)
			{
				hyductTerminal.Resistance = RevitUtils.PressureToInternal(parameter.AsDouble());
			}
			return hyductTerminal;
		}

		public static List<double> GetDuctSizes(Document doc, bool ductShape)
		{
			DuctSizeSettingIterator ductSizeSettingIterator = DuctSizeSettings.GetDuctSizeSettings(doc).GetDuctSizeSettingIterator();
			ductSizeSettingIterator.Reset();
			List<double> result = new List<double>();
			if (ductSizeSettingIterator.MoveNext())
			{
				KeyValuePair<DuctShape, DuctSizes> keyValuePair = ductSizeSettingIterator.Current;
				DuctShape key = keyValuePair.Key;
                if (ductShape && (int)key == 1)
				{
					keyValuePair = ductSizeSettingIterator.Current;
					result = RevitDataExchange.GetSizes(keyValuePair.Value.GetDuctSizeIterator());
				}
				if (!ductShape && key == null)
				{
					keyValuePair = ductSizeSettingIterator.Current;
					result = RevitDataExchange.GetSizes(keyValuePair.Value.GetDuctSizeIterator());
				}
			}
			return result;
		}

		public static bool AddDuctSize(Document doc, List<double> listSize, bool ductShape)
		{
			bool result;
			try
			{
				DuctSizeSettings ductSizeSettings = DuctSizeSettings.GetDuctSizeSettings(doc);
				foreach (double num in listSize)
				{
					MEPSize mepsize = new MEPSize(num, num, num, true, true);
					if (ductShape)
					{
                        ductSizeSettings.AddSize((DuctShape)1, mepsize);
					}
					else
					{
                        ductSizeSettings.AddSize((DuctShape)0, mepsize);
					}
				}
				result = true;
			}
			catch (Exception)
			{
				result = false;
			}
			return result;
		}

		private static List<double> GetSizes(DuctSizeIterator sizeIterator)
		{
			List<double> list = new List<double>();
			sizeIterator.Reset();
			while (sizeIterator.MoveNext())
			{
				MEPSize mepsize = sizeIterator.Current;
				list.Add(mepsize.NominalDiameter);
			}
			return list;
		}

		public static bool ToDuct(Duct element, ref HYDuctStraight hyStraight)
		{
			if (hyStraight.Shape == HYShapeProfile.Round)
			{
				RevitUtils.SetDistance(element, BuiltInParameter.RBS_CURVE_DIAMETER_PARAM, (double)hyStraight.Diameter / 1000.0);
			}
			else
			{
				RevitUtils.SetDistance(element, BuiltInParameter.RBS_CURVE_WIDTH_PARAM, (double)hyStraight.Width / 1000.0);
				RevitUtils.SetDistance(element, BuiltInParameter.RBS_CURVE_HEIGHT_PARAM, (double)hyStraight.Height / 1000.0);
			}
			return true;
		}
	}
}
